package utils;

import utils.node.DoubleNode;
import utils.node.Node;

/**
 * 链表工具类
 * @param <T>
 */
public class NodeUtils<T> {
    /**
     * 打印单链表结构，方便可视化观察
     *
     * @param node
     */
    public static void printSingleNode(Node node) {
        System.out.println("");
        while (null != node) {
            System.out.print(node.nextNode != null ? node.value + " -> " : node.value + " -> null");
            node = node.nextNode;
        }
    }

    /**
     * 打印节点(单列)
     *
     * @param node
     */
    public static void printDoubleNode(DoubleNode node) {
        System.out.println("======================================");
        while (null != node) {
            String nextPos = node.nextNode == null ? "" : " <=> ";
            System.out.print(node.value + nextPos);
            node = node.nextNode;
        }
        System.out.println("");
        System.out.println("======================================");
    }

    /**
     * 正向打印+逆向打印 观察双向链表结构（双列）
     *
     * @param node
     */
    public static void printDoubleNode2(DoubleNode node) {
        System.out.println("======================================");
        DoubleNode cur = null;
        // 从头遍历到尾
        while (null != node) {
            String nextPos = node.nextNode == null ? "" : " -> ";
            System.out.print(node.value + nextPos);
            // 抓一下尾节点
            cur = node;
            node = node.nextNode;
        }
        System.out.println("");
        // 从尾回溯到头;
        while (null != cur) {
            String lastPos = cur.lastNode == null ? "" : " -> ";
            System.out.print(cur.value + lastPos);
            cur = cur.lastNode;
        }
        System.out.println("");
        System.out.println("======================================");
    }

    /**
     * 将一个数组转成单向链表
     *
     * @param arr 一个数组[]
     * @return Node单项链表
     */
    public static Node constructNode(Object[] arr) {
        if (arr.length <= 0) {
            throw new RuntimeException("输入的数组长度<=0");
        }
        //先用base初始化第一个节点空间的位置
        Node base = new Node(0);
        //用head记录第一个起点空间地址，记作head；最后返回head
        Node head = base;
        for (int i = 0; i < arr.length; i++) {
            // 数组的第一个值给第一个节点存储；
            if (i == 0 && arr[i] != null) {
                base.value = arr[i];
            } else {
                // 新建一个节点，赋值
                Node node = new Node(arr[i]);
                // 加到当前节点后面
                base.nextNode = node;
                // 当前节点指针后移
                base = node;
            }
        }
        return head;
    }

    /**
     * 快速构造一个双向链表
     *
     * @param arr 输入数组[]
     * @return DoubleNode双向链表
     */
    public static DoubleNode constructDoubleNode(Object[] arr) {
        DoubleNode head = new DoubleNode(null);
        DoubleNode pre = null;
        for (int i = 0; i < arr.length; i++) {
            if (i == 0 && arr[i] != null) {
                head.value = arr[i];
                head.lastNode = pre;
                pre = head;
            } else {
                DoubleNode doubleNode = new DoubleNode(arr[i]);
                pre.nextNode = doubleNode;
                doubleNode.lastNode = pre;
                pre = doubleNode;
            }
        }
        return head;
    }
}
